package datasource

import (
	"bytes"
	"encoding/json"
	"fmt"
	"net/http"
	"sync"
	"time"
)

type statusData struct {
	ConnectorCommon
	RunTime uint64 `json:"run_time"`
	Cpu uint8 `json:"cpu"`
	Memory uint8 `json:"memory"`
	Disk uint8 `json:"disk"`
	CserverConnect uint8 `json:"cserver_connect"`
	CvpnConnectSuccess uint8 `json:"cvpn_connect_success"`
	CvpnConnectException uint8 `json:"cvpn_connect_exception"`
	DomainResolutionFailed uint16 `json:"domain_resolution_failed"`
	SessionCount uint32 `json:"session_count"`
	Token string `json:"token"`
}

type ConnectorStatus struct {
	mu sync.Mutex
	data statusData
}

var gPointStat *ConnectorStatus
var onceStatus sync.Once

func (s *ConnectorStatus) Collect()  interface{} {
	s.mu.Lock()
	defer s.mu.Unlock()

	// 收集数据

	// 获取cpu,mem,disk使用率
	cpu, _ := GetCpuPercent()
	mem, _ := GetMemPercent()
	disk, _ := GetDiskPercent("/opt")
	runtime, _ := GetRunTime()

	// 填充连接器基本信息
	GetBaseInfo()
	basInfo := GBaseInfo
	basInfo.MessageType = MsgStatus
	basInfo.ConditionCode = fmt.Sprintf("%d-%d-%s", 12, 2, "192.168.88.88")
	fmt.Println("base info : ", GBaseInfo)

	// 填充连接器状态信息
	statInfo := statusData {
		ConnectorCommon: basInfo,
		RunTime: runtime,
		Cpu: uint8(cpu),
		Memory: uint8(mem),
		Disk: uint8(disk),
		CserverConnect: 1,
		CvpnConnectSuccess: 9,
		CvpnConnectException: 0,
		DomainResolutionFailed: 0,
		SessionCount: uint32(50000),
	}
	return statInfo
}

func (s *ConnectorStatus) DataConvert(input interface{}) []byte {
	// 判断类型
	data, ok := input.(statusData)
	if !ok {
		return nil
	}

	// 填充token
	data.Token = GLoginRsp.Token

	js, err := json.Marshal(data)
	if err != nil {
		fmt.Printf("[point] convert failed : %v\n", err)
	}
	return js
}

func (s *ConnectorStatus) DataReport(msg []byte) bool {
	if GPointFactory.config.PointStatusUrl == "" || GPointFactory.config.PointClient == nil {
		fmt.Printf("[point] [status] report failed invalid args\n")
		return false
	}
	if GLoginRsp.Token == "" {
		fmt.Printf("[point] [status] can not get token\n")
		return false
	}

	// 构造请求
	//fmt.Printf("[point] [status] url : %s\n", GPointFactory.config.PointStatusUrl)
	//fmt.Printf("[point] [status] report msg : %s\n", string(msg))
	bodyBuf := bytes.NewBuffer(msg)
	req, err := http.NewRequest(HttpPost, GPointFactory.config.PointStatusUrl, bodyBuf)
	if err != nil {
		fmt.Printf("[point] [status] new report failed : %v\n", err)
		return false
	}
	req.Header.Set("Content-Type", "application/json")

	// 发送请求
	rsp, err := GPointFactory.config.PointClient.Do(req)
	if err != nil {
		fmt.Printf("[point] [status] send report failed : %v\n", err)
		return false
	}
	defer rsp.Body.Close()
	if rsp != nil {
		fmt.Println("rsp code   : ", rsp.StatusCode)
	}
	return true
}

func (s *ConnectorStatus) Work() {
	fmt.Printf("[point] status run...\n")
	for {
		// 数据收集
		data := s.Collect()
		// 转换
		msg := s.DataConvert(data)
		// 上报
		s.DataReport(msg)
		time.Sleep(time.Duration(GPointFactory.config.PointInterval) * time.Second)
	}
}

func CreatePointStat() (bool, *ConnectorStatus) {
	// 已经创建过实例，直接返回
	if gPointStat != nil {
		return true, gPointStat
	}
	ok := false
	onceStatus.Do(func() {
		gPointStat = &ConnectorStatus{}
		ok = true
		fmt.Printf("[point] status init success\n")
	})
	return ok, gPointStat
}
